/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.context.returns;

import java.net.SocketException;

import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.context.core.Context;
import org.zhiqim.httpd.context.core.Return;
import org.zhiqim.httpd.util.Responses;
import org.zhiqim.httpd.util.Scripts;
import org.zhiqim.httpd.util.Styles;
import org.zhiqim.kernel.util.Htmls;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.ZmlEngine;

/**
 * 响应处理结果
 *
 * @version v1.0.0 @author zouzhigang 2017-8-21 新建与整理
 */
public class ReturnResult implements Return
{
    private ReturnFrame returnFrame = new ReturnFrame();
    
    @Override
    public void process(HttpRequest request) throws SocketException
    {
        //1.如果是frame目标的，使用returnFrame
        if (request.getParameterBoolean(_PARAM_CALL_FRAME_))
        {
            returnFrame.process(request);
            return;
        }

        //2.如果有配置/conf/return/returnResult.zml的
        Context context = (Context)request.getContext();
        ZmlEngine engine = context.getZmlEngine();
        if (engine.hasZml(_PATH_RETURN_RESULT_))
        {
            returnTemplate.process(request, _PATH_RETURN_RESULT_, null);
            return;
        }
        
        //3.没有配置/conf/return/returnResult.zml的提交默认响应
        HttpResponse response = request.getResponse();
        String encoding = response.getCharacterEncoding();
        
        String zhiqimCss = request.getContextAttributeString(request.isMobile()?ZC_ZHIQIM_MOBILE_CSS:ZC_ZHIQIM_CSS);
        String zhiqimJs = request.getContextAttributeString(request.isMobile()?ZC_ZHIQIM_MOBILE_JS:ZC_ZHIQIM_JS);
        boolean hasZhiqimCssJs = !Validates.isEmpty(zhiqimCss) && !Validates.isEmpty(zhiqimJs);
        
        //3.1 Script头部
        StringBuilder strb = new StringBuilder();
        strb.append(_HTML_5_TYPE_).append(_BR_);
        strb.append(_HTML).append(_BR_);
        strb.append(_HEAD).append(_BR_);
        strb.append(Htmls.toTitle(request.getContextName()));
        strb.append(Htmls.toContentType(encoding));
        if (hasZhiqimCssJs)
        {//加载zhiqim.css/zhiqim.js
            strb.append(Styles.src(zhiqimCss)).append(_BR_);
            strb.append(Scripts.src(zhiqimJs)).append(_BR_);
        }
        strb.append(_SCRIPT_BR);
        
        //3.2 组装告警函数
        buildAlertMsgFunction(request, strb, hasZhiqimCssJs);
        
        //3.3 组装回调函数
        buildCallbackFunction(request, strb);
        
        //3.4 Script尾部
        strb.append(SCRIPT_).append(_BR_);
        strb.append(HEAD_).append(_BR_);
        strb.append(HTML_).append(_BR_);

        //4.最后输出
        Responses.printAndCommit(response, strb, log);
    }
    
    /** 组装告警函数 */
    private void buildAlertMsgFunction(HttpRequest request, StringBuilder strb, boolean hasZhiqimCssJs)
    {
        if (hasZhiqimCssJs)
        {//Z.onload BEGIN
            strb.append("Z.onload(function()").append(_BR_)
                .append("{").append(_BR_);
        }
            
        //对信息进行HTML和Script标签处理
        String message = request.getAlertMsg();
        if (Validates.isEmpty(message))
        {//没有消息的，直接执行回调函数
            if (hasZhiqimCssJs)
                strb.append(_FOUR_).append("callback();").append(_BR_);
            else
                strb.append("callback();").append(_BR_).append(_BR_);
            
        }
        else
        {//有消息的，弹出消息告警，后执行回调函数
            message = Scripts.formatAlertMsg(message);
            
            if (hasZhiqimCssJs)
            {
                String func = request.isResponseSuccess()?"success":"failure";
                strb.append(_FOUR_).append("Z.alert(\"").append(message).append("\", callback, {type: \"").append(func).append("\"});").append(_BR_);
            }
            else
            {
                strb.append("alert(\"").append(message).append("\");").append(_BR_);
                strb.append("callback();").append(_BR_).append(_BR_);
            }
        }
        
        if (hasZhiqimCssJs)
        {//Z.onload END
            strb.append("});").append(_BR_).append(_BR_);
        }
    }
    
    /** 组装回调函数 */
    private void buildCallbackFunction(HttpRequest request, StringBuilder strb)
    {
        //1.函数头
        strb.append("function callback()").append(_BR_)
            .append("{").append(_BR_);
        
        //2.跳转
        switch (request.getForceReturnType())
        {
        case -1:break;//没有redirect
        case 1:strb.append(_FOUR_).append("window.history.back();").append(_BR_);break;
        case 2:strb.append(_FOUR_).append("window.close();").append(_BR_);break;
        case 3:strb.append(_FOUR_).append("parent.Z.Dialog.close(location.hash, true);").append(_BR_);break;
        case 4:
        {//调用javascript
            String redirect = request.getRedirect(_UTF_8_);
            strb.append(_FOUR_).append(redirect.substring("javascript:".length())).append(_BR_);
            break;
        }
        default:
        {//缺省表示正常连接
            //1.先清除可能的回车换行
            String redirect = request.getRedirect(_UTF_8_);
            redirect = redirect.replaceAll("\r", "");
            redirect = redirect.replaceAll("\n", "");
            
            //2.判断是否是有效的地址
            //  2.1 支持绝对地址//开头或http(s)://开头,如//www.zhiqim.com/index.htm,http://www.zhiqim.com/index.htm
            //  2.2 支持基于虚拟目录如当前虚拟目录是/或/admin,则绝对路径如/zhiqim.htm在处理时自动转为/zhiqim.htm和/admin/zhiqim.htm
            //  2.3 其他认为是相对路径，如zhiqim.htm,../zhiqim.htm之类的路径
            if (redirect.startsWith("/") && !redirect.startsWith("//"))
            {//如果是绝对路径,自动加上虚拟目录
                redirect = request.getContext().getRootPath(redirect);
            }

            strb.append(_FOUR_);
            
            int target = request.getResponseStatus();
            if (target == _601_REDIRECT_PARENT_)
                strb.append("parent.location.href=\"");
            else if (target == _603_REDIRECT_TOP_)
                strb.append("top.location.href=\"");
            else
                strb.append("window.location.href=\"");
            
            strb.append(redirect).append("\";").append(_BR_);
        }
        }
        
        //3.函数结尾
        strb.append("}").append(_BR_);
    }
}
